home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 June / CHIP_CD_2004-06.iso / software / miranda_hit / files / mirinstsetup.exe / Miranda Installer 0.0.1.2 / XMLParse.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-04-20  |  5.4 KB  |  175 lines

  1. /*
  2.     Miranda Installer - Installs nightlies and Miranda addons.
  3.     Copyright (C) 2002-2003 Goblineye Entertainment
  4.  
  5.     Authors: Saar (Tornado) and Kai (kai_b)
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20. */
  21.  
  22. #include "XMLParse.h"
  23. #pragma hdrstop
  24.  
  25.  
  26.  
  27. bool XMLParser_FeedDocument(XMLParse_Handler NotifyFunc,char *lpszDoc,LPARAM lParam)
  28. {
  29.     char *szElementName = NULL; // name of an element (including the fancy stuff. i.e.: "</rdf:RDF>")
  30.     if (NotifyFunc == NULL)
  31.     {
  32.         return(false);
  33.     }
  34.  
  35.     // ok let's get started
  36.     lpszDoc = strchr(lpszDoc,'<');
  37.     // ok now we're at the beginning of the document (we skipped the XML version and encoding element)
  38.     while ((lpszDoc != NULL) && (*lpszDoc != '\0'))
  39.     {
  40.         // at this point lpszDoc always points at the beginning of a new element ('<asd>asd</asd>')
  41.         lpszDoc++; // skip the '<'
  42.  
  43.         // let's check for a comment
  44.         // special handling for comments
  45.         if (strncmp(lpszDoc,"!--",3) == 0) // this is a comment, let's skip it
  46.         {
  47.             char *lpEndComment = strstr(lpszDoc+3,"-->");
  48.             
  49.             if (lpEndComment == NULL) // damn
  50.             {
  51.                 return(false);
  52.             }
  53.  
  54.             lpszDoc = strchr(lpEndComment+3,'<'); // start after the next element
  55.             continue;
  56.         }
  57.         else if (*lpszDoc == '!') // DTD, ignore
  58.         {
  59.             // we need to skip it
  60.             lpszDoc = strchr(lpszDoc+1,'<'); // start after the next element
  61.             continue;
  62.         }
  63.         else if (strncmp(lpszDoc,"?xml",4) == 0) // part of the prolog
  64.         {
  65.             // we need to skip it
  66.             char *lpEndDeclare = strstr(lpszDoc+5,"?>");
  67.             
  68.             if (lpEndDeclare == NULL) // damn
  69.             {
  70.                 return(false);
  71.             }
  72.  
  73.             lpszDoc = strchr(lpEndDeclare+2,'<'); // start after the next element
  74.             continue;
  75.         }
  76.  
  77.         if (*lpszDoc == '/') // end of element!
  78.         {
  79.             lpszDoc++;
  80.             // notify: end element. data: lpszDoc. len: strchr(lpszDoc,'>') - lpszDoc
  81.             NotifyFunc(XMLPARSER_NOTIFY_ENDELEMENT,lpszDoc,strchr(lpszDoc,'>') - lpszDoc,lParam);
  82.             lpszDoc = strchr(lpszDoc,'<');
  83.             continue;
  84.         }
  85.  
  86.         bool fTagIsEmpty = false;
  87.         char *lpszEndStart = strchr(lpszDoc,'>'); // this is the end of the starting element
  88.  
  89.         if (*(lpszEndStart-1) == '/') // empty tag
  90.         {
  91.             // empty tags are handled pretty much normally, only we don't do any data checks or anything like that
  92.             fTagIsEmpty = true;
  93.             lpszEndStart--; // go back, it will be the end of the tag for now
  94.         }
  95.  
  96.         char *lpszEndNameElement = lpszEndStart; // this is in case of no parameters
  97.         for (char *index=lpszDoc;index < lpszEndStart;index++)
  98.         {
  99.             if ((*index == ' ') || (*index == '\t')) // tag ended
  100.             {
  101.                 lpszEndNameElement = index; // btw the end name element is always + 1 from the end of the name
  102.                 break;
  103.             }
  104.         }
  105.  
  106.         unsigned int uiLen = lpszEndNameElement - lpszDoc;
  107.  
  108.         if (!fTagIsEmpty) // we only need this if the tag is not empty
  109.         {
  110.             szElementName = new char[uiLen + 4]; // + 1 + 3 (3 - </   >)
  111.  
  112.             if (szElementName == NULL)
  113.             {
  114.                 return(false); // error
  115.             }
  116.  
  117.             lstrcpy(szElementName,"</");
  118.             strncat(szElementName,lpszDoc,uiLen);
  119.             szElementName[uiLen + 2] = '>';
  120.             szElementName[uiLen + 3] = '\0';
  121.         }
  122.  
  123.  
  124.         // ok now we notify mother base we found this crap
  125.         // notify: start element. data: lpszDoc. length: lpszEndNameElement - lpszDoc
  126.         NotifyFunc(XMLPARSER_NOTIFY_STARTELEMENT,lpszDoc,lpszEndNameElement - lpszDoc,lParam);
  127.  
  128.         if (lpszEndStart > lpszEndNameElement) // it means we had parameters somewhere in the middle
  129.         {
  130.             // we advance the pointer (skipping the spaces until the start of the arguments)
  131.             while ((*lpszEndNameElement == ' ') || (*lpszEndNameElement == '\t')) lpszEndNameElement++;
  132.             // notify: arguments. data: lpszEndNameElement. length: lpszEndStart - lpszEndNameElement
  133.             NotifyFunc(XMLPARSER_NOTIFY_ARGUMENTS,lpszEndNameElement,lpszEndStart - lpszEndNameElement,lParam);
  134.         }
  135.  
  136.         // ok now handle the end of the element + data
  137.         lpszDoc = ++lpszEndStart;
  138.  
  139.         if (fTagIsEmpty) // we move on
  140.         {
  141.             lpszDoc++; // one more
  142.             lpszDoc = strchr(lpszDoc,'<');
  143.             continue;
  144.         }
  145.  
  146.         char *lpEndOfElement = strstr(lpszDoc,szElementName); // we try to find the end of it
  147.  
  148.         if (lpEndOfElement == NULL) // can't be
  149.         {
  150.             delete [] szElementName;
  151.             return(false);
  152.         }
  153.         
  154.         for (index=lpszDoc;index < lpEndOfElement;index++)
  155.         {
  156.             if (*index == '<') // ok this is, well, not bad, but it means we don't have raw data
  157.             {
  158.                 break;
  159.             }
  160.         }
  161.  
  162.         delete [] szElementName;
  163.         szElementName = NULL;
  164.  
  165.         if (index == lpEndOfElement) // came to the end, we have raw data with no elements inside!
  166.         {
  167.             // notify: data. data: lpszDoc; len: lpEndOfElement - lpszDoc
  168.             // if lpEndOfElement == lpszDoc then no data
  169.             NotifyFunc(XMLPARSER_NOTIFY_DATA,lpszDoc,lpEndOfElement - lpszDoc,lParam);
  170.         }
  171.         lpszDoc = strchr(lpszEndStart,'<'); // we start all over again
  172.     }
  173.  
  174.     return(true);
  175. }